\documentclass[12pt,titlepage]{article}
\usepackage[spanish]{babel}
\usepackage[utf8]{inputenc}
\usepackage{amsfonts}
\usepackage{amsmath}
\usepackage{amssymb}

\usepackage{color}
\usepackage{graphicx} % para insertar imagenes
\usepackage{verbatim}

\newcommand{\VSP}{\vspace*{3em}}
\newcommand{\Pa}{\vspace{5mm}}

\title{{\sc\normalsize Sistemas Operativos}\\{\bf Trabajo Práctico Nº1\\ \Pa} {\texttt Grupo 12}}
\author{\begin{tabular}{lcr}
Carla Livorno & 424/08 & carlalivorno@hotmail.com\\Thomas Fischer & 489/08 & tfischer@dc.uba.ar
\end{tabular}}
\date{\VSP \normalsize{Septiembre 2010}}
%\date{}
\begin{document}
\begin{titlepage}
\maketitle
\end{titlepage}
\tableofcontents
\newpage

\begin{section}{Ejercicio 1}

	El programa 'misterioso' consiste en la comunicación de dos procesos (padre e hijo) mediante \texttt{pipes}.
	Cada uno de los procesos tiene entonces dos descriptores de archivos, uno correspondiente a la escritura y otro a la lectura.
	El proceso padre envia al hijo un mensaje (cadena de caracteres), este lo lee y escribe la longitud de la cadena recibida que es leida por el proceso padre.\\

	Para ejecutar este programa se hacen las siguiente llamadas al sistema:
	\begin{itemize}
		\item {\bf execve:} Es para comenzar a ejecutar el programa 'mister'. Cuando se ingresa un comando al shell (en este caso ./mister) se produce un proceso nuevo (fork). Este proceso hijo deberá ejecutar el comando del usuario, cosa que hace con esta llamada al sistema, la cual causa que toda su imagen de núcleo sea reemplazada por el archivo que se nombra en su primer parámaetro.

		\item {\bf brk:} Es para cambiar el tamaño del segmento de datos.

		\item {\bf set\_thread\_area:} Es para registrar memoria local del thread que está corriendo.

		\item {\bf pipe:} Es para crear el pipe, canal unidireccional que pueden usar los procesos para su comunicación.

		\item {\bf clone:} Es para crear al proceso hijo con quien va a establecer la comunicación.
	
		\item {\bf write, read y close:} Estas llamadas al sistema son para el manejo de los descriptores de archivos. Las dos primeras envian y reciben mensajes respectivamente. La última es para terminar la comunicación.

		\item {\bf exit\_group:} Termina el proceso y todos sus threads.
	\end{itemize}
	
		Una vez que el padre envia el mensaje 'chau' cierra sus descriptores de archivos, el hijo lee este mensaje escribe un 4 (longitud de la cadena recibida) luego escribe un 0 y cierra también sus descriptores de archivos. \color{red}{Esto no siempre ocurre en el mismo orden ¿por el scheduler?, es decir si el padre cierra primero sus descriptores de archivo, cuando el hijo intente escribir su último mensaje recibirá la señal \texttt{SIGPIPE} ya que esta intentando escribir un mensaje que ya no va a poder ser leido. En cambio si es el hijo quien hace el $exit\_group$ el padre recibirá la señal \texttt{SIGCHLD} que le avisa que el hijo terminó.}

\end{section}

\begin{section}{Ejercicio 2}

	En la segunda parte del taller escribimos un programa que ejecuta
	un comando pasado como parámetro como un proceso hijo, y mata al
	mismo si este trata de ejecutar un syscall de tipo \texttt{clone} o
	\texttt{fork}. \\

	Para esto usamos las syscall ptrace, la cuál nos provee una forma
	de monitorear las llamadas al sistema de procesos hijos. \\

	Para usarla, necesitamos que luego de un fork, el proceso hijo se
	detenga y avise mediante una señal que se produjo alguna syscall.
	Para esto, en el hijo, ejecutamos la llamada ptrace
	con un request de tipo \texttt{TRACEME}. \\

	Luego, desde el padre, debemos esperar hasta que el hijo envíe una señal.
	Esto lo hacemos con la función bloqueante \texttt{wait},
	que al producirse una cambio de estado en algún proceso hijo,
	por ejemplo al llamar a una syscall,
	se desbloquea devolviendonos el \texttt{pid} del mismo y escribe
	en una variable información suficiente para determinar los detalles de la señal.

	Una vez que obtenemos el aviso en el padre, nos fijamos si la señal
	fue producida porque el proceso hijo hizo una syscall mediante la macro \texttt{WIFSTOPPED},
	y en caso afirmativo preguntamos si fue una de las dos que queremos evitar,
	usando el número de entrada de las mismas en la tabla de llamadas al sistema,
	$2$ para \texttt{fork} y $120$ para \texttt{clone}.
	
	Como el número de syscall queda registrado en el registro \texttt{eax}
	cuando llamamos a la \texttt{int 80}, podemos acceder al contenido del mismo
	que quedó guardado en la entrada de la tabla de procesos cuando
	se produjo el último cambio de contexto al interrumpirse el programa,
	mediante el request \texttt{PTRACE\_PEEKUSER} de la función \texttt{ptrace},
	con el offset del registro en la tabla, que conocemos por la macro \texttt{ORIG\_EAX}.

	Si se produjo alguna de estas dos, matamos inmediatamente al proceso hijo
	enviandole una señal de tipo \texttt{SIGKILL} mediante \texttt{Pptrace},
	luego de lo cuál terminamos el programa. \\

	Por otro lado, si la señal de \texttt{wait} se produjo
	porque el proceso hijo termino correctamente, también terminamos el programa. \\

	En cualquier otro caso, continuamos la ejecución del programa hijo
	hasta la próxima señal usando la función \texttt{ptrace}
	con un request de tipo \texttt{PTRACE\_SYSCALL}.

\end{section}

\end{document}
